package com.lightkits.wms.domain.deliveryorder.service.impl;

import com.lightkits.common.db.entity.BdDeliveryOrderBase;
import com.lightkits.common.db.entity.event.BdEvent;
import com.lightkits.common.db.entity.event.BdEventRecord;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.wms.domain.deliveryorder.model.EventParams;
import com.lightkits.wms.domain.deliveryorder.repo.DeliveryOrderDBService;
import com.lightkits.wms.domain.deliveryorder.service.CancelDeliveryDomain;
import com.lightkits.wms.domain.deliveryorder.service.CreateDeliveryEventDomain;
import com.lightkits.wms.domain.saveonhand.repo.BdEventRecordService;
import com.lightkits.wms.domain.saveonhand.repo.BdEventService;
import com.lightkits.wms.dto.deliveryorder.model.DeliveryCancelDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * CancelDeliveryDomianImpl
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/2/27 18:51
 */
@Service
public class CancelDeliveryDomianImpl implements CancelDeliveryDomain {

    private final CreateDeliveryEventDomain createDeliveryEventDomain;

    private final BdEventRecordService bdEventRecordService;

    private final BdEventService bdEventService;

    private final DeliveryOrderDBService deliveryOrderDBService;

    @Autowired
    public CancelDeliveryDomianImpl(CreateDeliveryEventDomain createDeliveryEventDomain, BdEventRecordService bdEventRecordService, BdEventService bdEventService, DeliveryOrderDBService deliveryOrderDBService) {
        this.createDeliveryEventDomain = createDeliveryEventDomain;
        this.bdEventRecordService = bdEventRecordService;
        this.bdEventService = bdEventService;
        this.deliveryOrderDBService = deliveryOrderDBService;
    }

    /**
     * 取消发货单发货创建
     *
     * @param dto 取消发货单参数
     * @return
     */
    private CheckResult<BdDeliveryOrderBase> cancelDelivery(DeliveryCancelDTO dto) {
        CheckResult<BdDeliveryOrderBase> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        if (ObjectUtil.isEmpty(dto) || ObjectUtil.isNullOrEmpty(dto.getDeliveryOrderId())) {
            return checkResult.fail("the delivery is null");
        }
        BdDeliveryOrderBase deliveryOrderBase = new BdDeliveryOrderBase().selectById(dto.getDeliveryOrderId());
        if (ObjectUtil.isEmpty(deliveryOrderBase)) {
            return checkResult.fail("the deliveryId is invalid");
        }
        deliveryOrderBase.setStatus("CANC");
        List<BdEvent> events = new ArrayList<>();
        EventParams params = convertParams(deliveryOrderBase, dto);
        CheckResult<BdEvent> eventIResult = createDeliveryEventDomain.createEvent(params);
        if (!eventIResult.isSuccessful() || ObjectUtil.isEmpty(eventIResult.getData())) {
            eventIResult.fill(checkResult);
            return checkResult;
        }
        events.add(eventIResult.getData());
        deliveryOrderBase.store(events);
        checkResult.setData(deliveryOrderBase);
        return checkResult;
    }

    /**
     * 取消发货单参数转换
     *
     * @param dto               发货单
     * @param deliveryCancelDTO 取消发货单参数
     * @return
     */
    private EventParams convertParams(BdDeliveryOrderBase dto, DeliveryCancelDTO deliveryCancelDTO) {
        EventParams params = new EventParams();
        params.setRecordType("STATUS");
        params.setOrgId(dto.getOrganizationId().toString());
        params.setParentEventId(deliveryCancelDTO.getParentEventId());
        params.setWorkerId(deliveryCancelDTO.getWorkerId());
        params.setObjectType("DELIVERY_ORDER");
        params.setObjectId(dto.getId());
        params.setKeyValue("CANC");
        params.setEventTypeCode("DELIVERY_ORDER_CANC");
        return params;
    }

    /**
     * 取消发货单
     *
     * @param dto 取消发货单参数
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult insertValue(DeliveryCancelDTO dto) {
        CheckResult<BdDeliveryOrderBase> checkResult = cancelDelivery(dto);
        if (!checkResult.isSuccessful() || ObjectUtil.isEmpty(checkResult.getData())) {
            return IResult.fail(checkResult.getMessage());
        }
        BdDeliveryOrderBase base = checkResult.getData();
        //insert delivery Order
        boolean createDEliveryFlag = deliveryOrderDBService.updateById(base);
        if (!createDEliveryFlag) {
            throw new LightKitsBizException("Update DeliveryOrder for Cancel error.");
        }

        List<BdEvent> eventBase = new ArrayList<>();
        List<BdEventRecord> eventRecordBase = new ArrayList<>();
        List<Object> events = base.take();
        for (Object object : events) {
            if (object.getClass().equals(BdEvent.class)) {
                BdEvent event = (BdEvent) object;
                eventBase.add(event);
            }
        }
        boolean insertEventFlag = bdEventService.insertBatch(eventBase);
        if (!insertEventFlag) {
            throw new LightKitsBizException("Save events for Cancel error.");
        }

        //insert eventRecords and onhandJournals
        for (BdEvent event : eventBase) {
            List<Object> records = event.take();
            for (Object object : records) {
                if (object.getClass().equals(BdEventRecord.class)) {
                    BdEventRecord record = (BdEventRecord) object;
                    record.setEventId(event.getId());
                    eventRecordBase.add(record);
                }
            }
        }

        boolean insertRecordsFlag = bdEventRecordService.insertBatch(eventRecordBase);
        if (!insertRecordsFlag) {
            throw new LightKitsBizException("Save eventRecords for Cancel error.");
        }
        return IResult.success();
    }
}
